#include <stdio.h>
#include <pthread.h>
void* writer(void*);
void* reader(void*);
typedef struct
{
	int data;
	int write;/* 0表示不能写数据，1表示可以写数据 */
	int read;/* 0表示不能读数据，1表示可以读数据 */
	int length;
	pthread_cond_t write_cond;
	pthread_cond_t read_cond;
	pthread_mutex_t write_mutex;
	pthread_mutex_t read_mutex;
}Data;
int main(void)
{
	Data data = {0,0,1,3};
	pthread_cond_init(&data.write_cond,NULL);
	pthread_cond_init(&data.read_cond,NULL);
	pthread_mutex_init(&data.write_mutex,NULL);
	pthread_mutex_init(&data.read_mutex,NULL);
	pthread_t thread1_id,thread2_id;
	pthread_create(&thread1_id,NULL,writer,(void*)&data);
	pthread_create(&thread2_id,NULL,reader,(void*)&data);
	pthread_join(thread1_id,NULL);
	pthread_join(thread2_id,NULL);
	return 0;
}
/* 得到reader方法通知写数据，再通知writer方法写数据，并阻塞等待reader方法读数据  */
void* writer(void* data)
{
	Data* d = (Data*)data;
	for(int i = 0;i < d->length;i++)
	{
		pthread_mutex_lock(&d->write_mutex);
		while(d->write == 0)
		{
			pthread_mutex_unlock(&d->write_mutex);
			usleep(0.1);
			pthread_mutex_lock(&d->write_mutex);
		}
		printf("write %d\n",d->data);
		d->write = 0;
		d->read = 1;
		pthread_mutex_unlock(&d->write_mutex);
		pthread_cond_broadcast(&d->read_cond);
		if(i < ( d->length - 1) )
		{
			pthread_cond_wait(&d->write_cond,&d->write_mutex);
			pthread_mutex_unlock(&d->write_mutex);
		}
	}
	return (void*)NULL;
}
/* 读数据方法，先读数据，再通知writer方法写一个数据，并阻塞等write方法通知 */
void* reader(void* data)
{
	Data* d = (Data*)data;
	for(int i = 0;i < d->length;i++)
	{
		pthread_mutex_lock(&d->write_mutex);
		d->data = i;
		d->write = 1;
		printf("read %d\n",d->data);
		pthread_cond_broadcast(&d->write_cond);
		while(d->read == 0)
		{
			pthread_mutex_unlock(&d->write_mutex);
			usleep(0.1);
			pthread_mutex_lock(&d->write_mutex);
		}
		d->read = 0;
		pthread_mutex_unlock(&d->write_mutex);
		if(i < ( d->length - 1) )
		{
			pthread_cond_wait(&d->read_cond,&d->read_mutex);
			pthread_mutex_unlock(&d->read_mutex);
		}
	}
	return (void*)NULL;
}
